package controller;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;

import view.Gui;


/**
 * This class provides background functions for the game Super-Brain like generating the secret colors and
 * comparing the guess to the secret colors.
 */



public class Controller {

	private ArrayList<ArrayList<Color>> colorField = new ArrayList<ArrayList<Color>>();
	private int rightPlace;
	private int rightColor;
	private int roundNumber = 1;
	private int moveNumber = 0;
	private boolean won = false;
	private Gui view;
	
	private ArrayList<Color> secretColors;
	private Hashtable<String, Color> possibleColors = new Hashtable<String, Color>();
	
	//constructor
	public Controller(){
		resetProgram();
	}
	
	/**
	 * add colors to a list where the secret colors can be chosen from
	 */
	
	public void addColorsToList()
	{
		possibleColors.put("black", Color.black ); 
		possibleColors.put("blue", Color.blue);
		possibleColors.put("brown", new Color(139,69,19));
		possibleColors.put("yellow", Color.yellow );
		possibleColors.put("purple", new Color(160,32,240));
		possibleColors.put("green", new Color(34,139,34));
	}
	
	/**
	 * entered colors from the player will be saved to provide them for the evaluation
	 * @param colorCode
	 * @return
	 */
	public boolean saveColors(Color [] colorCode)
	{
		ArrayList <Color> c = new ArrayList<Color>();
		
		//saving the colors from an Array into an ArrayList (to enable the adding to the list of all his guesses)
		for (int i = 0 ; i < colorCode.length ; i++)
		{
			c.add(colorCode[i]);
		}
		
		//adding of player's guess to a list of all his guesses
		colorField.add(c);
		
		//check the entered color combination
		won= checkGuess();
		return won;
	}
	
	/**
	 * Evaluates the player's guess. Returns true if the player has won otherwise false
	 * @return
	 */
	public boolean checkGuess()
	{
		//no elements in the list
		if (colorField.size() < 1 || secretColors.size() < 1)
			return false;
		
		// the lists have elements that can be compared
		else
		{	
			rightPlace = 0;
			rightColor = 0;
			//check every color of the player's guess if it match the color and place or just the color
			//check every position of the secret color alone
			for(int i = 0; i < 4; i++)
			{
				//get the last guess of the player
				ArrayList<Color> guess = (colorField.get(roundNumber - 1));
				//get the first of the four colors of the secret combination
				Color secret = (secretColors.get(i));
				
				//same position and same Color
				if (guess.get(i).equals(secret))
				{
					rightPlace++;
				}
				//right color but wrong place
				else
				{
					for (int j = 0 ; j < 4; j++)
					{
						if (guess.get(j).equals(secret))
							rightColor++;
					}
				}
			}
			
			//WON!!!!
			if (rightPlace == 4)
			{
				won = true;
				//ask the player if he would like to play again
				view.playAgain(won);
				return true;
			}
	}	
		return false;
}	
	
	/**
	 * reset the program to the beginning state to enable another round
	 */
	public void resetProgram()
	{
		this.moveNumber = 0;
		this.roundNumber = 1;
		rightColor = 0;
		rightPlace = 0;
		possibleColors.clear();
		colorField.clear();
		addColorsToList();
		//get new random colors
		secretColors = getRandomColor();
		won = false;
	}
	
	/**
	 * create the secret colors randomly
	 * @return
	 */
	public ArrayList<Color> getRandomColor()
	{		
		ArrayList <Color> c = new ArrayList<Color>(possibleColors.values());
		Collections.shuffle(c);
		
		//delete elements of the ArrayList until there are just four left
		while(c.size() > 4)
		{
			c.remove(0);
		}
		return c;
	}
	
	/**
	 * counts the number of moves and control if they are valid
	 * @return
	 */
	public boolean nextMove()
	{
		moveNumber++;
		//controls that a player can just choose four colors per guess
		if (moveNumber < 4)
		{
			return true;
		}
		else 
		{
			moveNumber = 0;
			return false;
		}
	}
	
	/**
	 * counts the number of rounds and control if they are valid
	 * @return
	 */
	public boolean nextRound()
	{
		//controls that a player has only ten guesses to get the right color combination
		if (roundNumber < 10)
		{
			roundNumber++;
			return true;
		}
		else 
		{
			roundNumber=1;
			view.playAgain(won);
			return false;
		}
	}
	
	
	//------------------------------------------------
	//GETTER and SETTER
	
	public int getRoundNumber()
	{
		return this.roundNumber;
	}
	
	

	public Color getRGB(String str)
	{
		return possibleColors.get(str.toLowerCase());
	}
	
	public ArrayList<Color> getSecretColors()
	{
		return secretColors;
	}
	
	public ArrayList<ArrayList<Color>> getSavedColors()
	{
		return colorField;
	}	
	
	public int getNumberRightPlace()
	{
		return rightPlace;
	}
	
	public int getNumberRightColor()
	{
		return rightColor;
	}
	
	public void setGui(Gui gui){
		this.view=gui;
	}
}